home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Various / DevDisk 65 (1989)(DevWare PD).zip / DevDisk 65 (1989)(DevWare PD).adf / prosuite / xtextsup.c < prev   
C/C++ Source or Header  |  1990-07-11  |  16KB  |  508 lines

  1.  
  2. /* *** xtextsup.c ***********************************************************
  3.  *
  4.  * XText  --  Support Procedures
  5.  *    from Book 1 of the Amiga Programmers' Suite by RJ Mical
  6.  *
  7.  * Copyright (C) 1986, 1987, Robert J. Mical
  8.  * All Rights Reserved.
  9.  *
  10.  * Created for Amiga developers.
  11.  * Any or all of this code can be used in any program as long as this
  12.  * entire notice is retained, ok?  Thanks.
  13.  *
  14.  * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  15.  * All copyright notices and all file headers must be retained intact.
  16.  * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the 
  17.  * resultant object code may be included in any software product.  However, no 
  18.  * portion of the source listings or documentation of the Amiga Programmer's 
  19.  * Suite Book 1 may be distributed or sold for profit or in a for-profit 
  20.  * product without the written authorization of the author, RJ Mical.
  21.  * 
  22.  * HISTORY       NAME            DESCRIPTION
  23.  * -----------   --------------  --------------------------------------------
  24.  * 27 Oct 86     RJ              Add XText buffer stuff, prepare for release
  25.  * March 86      RJ              Incorporated this code in Sidecar
  26.  * 26 Jan 86     RJ Mical        Created this file (on my birthday!)
  27.  *
  28.  * *********************************************************************** */
  29.  
  30.  
  31. #include "xtext.h"
  32.  
  33.  
  34. VOID UnmakeXTextSupport();
  35.  
  36.  
  37. struct TextAttr DefaultXTextFont =
  38.         {
  39.         (UBYTE *)"topaz.font",
  40.         TOPAZ_EIGHTY,
  41.         0,
  42.         FS_NORMAL
  43.         };
  44.  
  45.  
  46. UBYTE *AllocXTextPlane(xtext)
  47. struct XTextSupport *xtext;
  48. /* This routine allocates an XText text plane, with one byte for each
  49.  * line of each character in the widest allowable line.
  50.  */
  51. {
  52.     return (AllocRemember(&xtext->XTextKey, 
  53.             xtext->MaxTextWidth * xtext->CharHeight,
  54.             MEMF_CLEAR | MEMF_CHIP));
  55. }
  56.  
  57.  
  58.  
  59. VOID AttachRemember(tokey, fromkey)
  60. struct Remember **tokey, **fromkey;
  61. /* Attach the contents of a Remember key to the allocations of another
  62.  * Remember key.
  63.  */
  64. {
  65.     struct Remember *workkey;
  66.  
  67.     if ((workkey = *tokey) == NULL) *tokey = *fromkey;
  68.     else
  69.         {
  70.         while (workkey->NextRemember) workkey = workkey->NextRemember;
  71.         workkey->NextRemember = *fromkey;
  72.         }
  73.     *fromkey = NULL;
  74. }
  75.  
  76.  
  77.  
  78. VOID MakeXTextFontData(font, style, bufptr, xtext)
  79. struct TextFont *font;
  80. USHORT style;
  81. UBYTE *bufptr;
  82. struct XTextSupport *xtext;
  83. /* This awful little routine fills the buffer with the XText-style
  84.  * font imagery.  The font is set to reflect the desired style, if any,
  85.  * and then one character at a time is drawn (using Text()) into
  86.  * a temporary rastport and then copies the character imagery into
  87.  * the XText buffer.
  88.  */
  89. {
  90.     SHORT i, i2;
  91.     UBYTE text;
  92.     SHORT baseline, height, xoffset, bytewidth;
  93.     SHORT extracolumn, movecolumn;
  94.     LONG enable;
  95.     UBYTE *ptr;
  96.     struct RastPort *rport;
  97.     struct BitMap *bmap;
  98.     struct TmpRas *tmpras;
  99.     struct Remember *localKey;
  100.  
  101.     localKey = NULL;
  102.     rport = (struct RastPort *)AllocRemember(&localKey,
  103.             sizeof(struct RastPort), NULL);
  104.     bmap = (struct BitMap *)AllocRemember(&localKey,
  105.             sizeof(struct BitMap), NULL);
  106.     tmpras = (struct TmpRas *)AllocRemember(&localKey,
  107.             sizeof(struct TmpRas), NULL);
  108.     if ((rport == NULL) || (bmap == NULL) || (tmpras == NULL))
  109.         goto DONE;
  110.  
  111.     bytewidth = xtext->MaxTextWidth;
  112.     height = xtext->CharHeight;
  113.  
  114.     InitBitMap(bmap, 1, bytewidth * XTEXT_CHARWIDTH, height);
  115.     bmap->Planes[0] = xtext->NormalTextPlane;
  116.     InitRastPort(rport);
  117.     rport->BitMap = bmap;
  118.     rport->TmpRas = InitTmpRas(tmpras, xtext->InverseTextPlane,
  119.             bytewidth * height);
  120.  
  121.     SetAPen(rport, 1);
  122.     SetBPen(rport, 0);
  123.     SetDrMd(rport, JAM2);
  124.  
  125.     SetFont(rport, font);
  126.     enable = AskSoftStyle(rport);
  127.     SetSoftStyle(rport, style, enable);
  128.  
  129.     baseline = rport->TxBaseline;
  130.  
  131.     /* Now, italics are a real pain in the ascii.
  132.      * An 8-bit-wide font is normally wider than 8 bits when rendered 
  133.      * in italics, so some of the character data must be lost.  
  134.      * You can set the xoffset variable to some alternate value 
  135.      * if you want an alternate slice of the font data.
  136.      * 
  137.      * Furthermore, I just spent several hours discovering that 
  138.      * the Text() routine creates the italics by shifting the lines above
  139.      * the baseline to the right *and* by shifting the lines below the
  140.      * baseline to the left.  So what, you ask?  Well, if a character 
  141.      * is printed starting at column 0, in a RastPort 
  142.      * unprotected by a Layer, then those left-shifted bits 
  143.      * tickle the nose of the guru, doncha know.  Achoo!  Blink blink blink.
  144.      */
  145.  
  146.     xoffset = 0;
  147.     /* See the comment above regarding xoffset */
  148.     if (style & FSF_ITALIC) xoffset = ITALIC_LEFT_EDGE;
  149.  
  150.     /* Text is drawn at least at column 8, and perhaps even further 
  151.      * to the right if the left-shift of italics makes it necessary.
  152.      */
  153.     extracolumn = ((height - baseline) - 1) >> 3;
  154.     movecolumn = (8 + (extracolumn << 3)) - xoffset;
  155.  
  156.     for (i = 0; i < 256; i++)
  157.         {
  158.         text = i;
  159.  
  160.         /* Finally, move the pens to our spot and draw the next character */
  161.         Move(rport, movecolumn, baseline);
  162.         Text(rport, &text, 1);
  163.  
  164.         /* Now copy that character in XText font format into the buffer. */
  165.         ptr = bmap->Planes[0] + 1 + extracolumn;
  166.         for (i2 = 0; i2 < height; i2++)
  167.             {
  168.             *bufptr++ = *ptr;
  169.             if (FlagIsClear(xtext->Flags, SLIM_XTEXT)) *bufptr++ = 0;
  170.             ptr += bytewidth;        /* Skip to the next row */
  171.             }
  172.         }
  173.  
  174. DONE:
  175.     FreeRemember(&localKey, TRUE);
  176. }
  177.  
  178.  
  179.  
  180. /* *** MakeXTextFont() ******************************************************
  181.  * 
  182.  * NAME
  183.  *    MakeXTextFont  --  Make font imagery for the XText routines
  184.  * 
  185.  * 
  186.  * SYNOPSIS
  187.  *    UBYTE *MakeXTextFont(TextAttr, XTextSupport, Index);
  188.  * 
  189.  * 
  190.  * FUNCTION
  191.  *    This routine creates font imagery in the format that the XText()
  192.  *    routine uses.  It allocates the font data buffer and then constructs
  193.  *    the XText font imagery in this buffer using the imagery of the
  194.  *    font specified by the TextAttr argument.
  195.  *    
  196.  *    This routine is normally called by MakeXTextSupport().  You do not
  197.  *    need to use this routine unless you want to create fonts that
  198.  *    have special styles such as bold, underline, and italics.
  199.  *    
  200.  *    If all is successful, this routine writes the address of the font 
  201.  *    data buffer in the XTextSupport's FontData array at the Index position,
  202.  *    and returns the address of the new font data buffer.  
  203.  *    If anything goes wrong, the FontData array is unchanged and this 
  204.  *    routine returns NULL.
  205.  *    
  206.  *    You can specify font styles in your TextAttr structure.
  207.  *    If the TextAttr argument is equal to NULL, the system's 80-column 
  208.  *    "topaz.font" will be used instead.
  209.  *    
  210.  *    You must have called MakeXTextSupport() before calling this routine,
  211.  *    as this routine requires an initialized XTextSupport structure.
  212.  *    All memory allocations are attached to the XTextSupport structure's
  213.  *    Remember key.
  214.  *    
  215.  *    
  216.  * INPUTS
  217.  *    TextAttr = a pointer to a TextAttr structure specifying the font
  218.  *       to be used for this XText font imagery.  If the TextAttr
  219.  *       argument is equal to NULL, the system's 80-column "topaz.font"
  220.  *       will be used.
  221.  *    
  222.  *    XTextSupport = a pointer to an initialized XTextSupport structure,
  223.  *       which structure is created by a call to MakeXTextSupport().
  224.  *    
  225.  *    Index = index into the XTextSupport's FontData array for this font
  226.  *    
  227.  *    
  228.  * RESULT
  229.  *    Returns a pointer to the memory block that contains the font imagery.
  230.  *    If anything goes wrong (usually out of memory), returns NULL.
  231.  *    
  232.  *    
  233.  * EXAMPLE
  234.  *      struct XTextSupport *xtext;
  235.  *      struct TextAttr localTextAttr = { ... };
  236.  *      xtext = MakeXTextSupport();
  237.  *    [Make a BOLD font for XText() calls]
  238.  *      localTextAttr.ta_Style = FSF_BOLD;
  239.  *      MakeXTextFont(&localTextAttr, xtext, BOLD_FONT);
  240.  *    [Write some BOLD characters]
  241.  *      xtext->FontSelect = BOLD_FONT;
  242.  *      XText(...);
  243.  *
  244.  * BUGS
  245.  *    Well, if there is a bug it's a highly technical one that most
  246.  *    of you can ignore.  I'm not sure that it's entirely 100% for sure 
  247.  *    safe to work with DiskfontBase the way I have below and still expect
  248.  *    this program to be re-entrant.  It should be OK up to and including 
  249.  *    the 1.2 release of the system, but in the future this could cause
  250.  *    some very mysterioso bug.
  251.  *    
  252.  *    
  253.  * SEE ALSO
  254.  *    MakeXTextSupport(), XText(), UnmakeXTextSupport()
  255.  */
  256. UBYTE *MakeXTextFont(textattr, xtext, index)
  257. struct TextAttr *textattr;
  258. struct XTextSupport *xtext;
  259. SHORT index;
  260. /* === Get our special expanded-data font === */
  261. {
  262.     struct TextFont *localfont;
  263.     BOOL openedlib, success;
  264.     UBYTE *data;
  265.     struct Remember *localkey;
  266.     SHORT size;
  267.  
  268.     openedlib = success = FALSE;
  269.     localkey = NULL;
  270.     localfont = NULL;
  271.  
  272.     /* If the user has specified no font, use 80-column "topaz.font" */
  273.     if (textattr == NULL) textattr = &DefaultXTextFont;
  274.  
  275.     /* Allocate a special-character buffer where there are 256 characters
  276.      * and each character is CharHeight tall.  If not SLIM_XTEXT, make the 
  277.      * text two bytes wide for each character.
  278.      */
  279.     size = 256 * xtext->CharHeight;
  280.     if (FlagIsClear(xtext->Flags, SLIM_XTEXT)) size *= 2;
  281.     if ((data = AllocRemember(&localkey, size, MEMF_CHIP)) == NULL)
  282.         goto DONE;
  283.  
  284.     /* Attempt to open the specified font */
  285.     if ((localfont = OpenFont(textattr)) == NULL)
  286.         {
  287.         if ((DiskfontBase = (struct DiskfontBase *)
  288.                 OpenLibrary("diskfont.library", 0)) == NULL)
  289.             goto DONE;
  290.         openedlib = TRUE;
  291.  
  292.         if ((localfont = OpenDiskFont(textattr)) == NULL) goto DONE;
  293.         }
  294.  
  295.     /* localfont is opened.  Transform the data into XText format */
  296.     MakeXTextFontData(localfont, textattr->ta_Style, data, xtext);
  297.  
  298.     CloseFont(localfont);
  299.  
  300.     success = TRUE;
  301.  
  302. DONE:
  303.     if (openedlib) CloseLibrary(DiskfontBase);
  304.     if (success)
  305.         {
  306.         AttachRemember(&xtext->XTextKey, &localkey);
  307.         xtext->FontData[index] = data;
  308.         }
  309.     else 
  310.         {
  311.         FreeRemember(&localkey, TRUE);
  312.         data = NULL;
  313.         }
  314.  
  315.     return(data);
  316. }
  317.  
  318.  
  319.  
  320. /* *** MakeXTextSupport() ***************************************************
  321.  * 
  322.  * NAME
  323.  *    MakeXTextSupport  --  Allocate and initialize XText Support data
  324.  * 
  325.  * 
  326.  * SYNOPSIS
  327.  *    struct XTextSupport *MakeXTextSupport(RastPort, TextAttr, 
  328.  *          MaxTextWidth, InitialFlags);
  329.  * 
  330.  * 
  331.  * FUNCTION
  332.  *    This routine allocates an XTextSupport structure and initializes
  333.  *    the structure for use by the XText routines.
  334.  * 
  335.  *    The font specified by the TextAttr argument is opened.  If the
  336.  *    TextAttr arg is equal to NULL, the system font "topaz.font" is
  337.  *    opened instead.  If you are specifying a TextAttr, the font you
  338.  *    specify must have a character cel that is 8-bits wide.
  339.  * 
  340.  *    Image data from this font is then used to create the special
  341.  *    font data used by the XText routines.  The address of this data
  342.  *    is put in the FontData variable of the XTextSupport structure,
  343.  *    as well as in all of the elements in the SpecialFontData array.
  344.  * 
  345.  *    The MaxTextWidth argument describes the maximum number of 
  346.  *    characters that you will ever print at one time with the 
  347.  *    XText() routine.  Typically this number will be 80 or 40, 
  348.  *    depending on whether your display is high-res or low-res.  
  349.  *    This number should be an even number; if the number you 
  350.  *    supply is odd, the actual number used will be your number 
  351.  *    rounded up to the next even number.
  352.  * 
  353.  *    The InitialFlags argument is used to preset your XTextSupport's
  354.  *    Flags variable before anything is done with the structure.  
  355.  *    See the file xtext.h for the definitions of the XTextSupport 
  356.  *    structure's Flags.
  357.  * 
  358.  *    An InitialFlag of note is the SLIM_XTEXT flag, which you can 
  359.  *    set to define that you want the slim (and slow) XText technique 
  360.  *    to be used when the XText font data is created and when 
  361.  *    XText is rendered to the display.  The advantage of SLIM_XTEXT 
  362.  *    is that the technique requires half as much memory as the 
  363.  *    fast fat technique.  The disadvantage is that it runs about 
  364.  *    20% more slowly than fast fat XText.  
  365.  * 
  366.  *    After you have called MakeXTextSupport(), you can use
  367.  *    the Remember key in the XTextSupport structure -- named
  368.  *    XTextKey -- for further memory allocations.  All memory
  369.  *    allocations made using XTextKey are freed when 
  370.  *    UnmakeXTextSupport() is called.
  371.  * 
  372.  * 
  373.  * INPUTS
  374.  *    RastPort = a pointer to the RastPort that will be the destination
  375.  *       for text created by the XText routines.  Typically, this
  376.  *       will be the RastPort of an Intuition window or screen
  377.  *       that you've opened.  For an example, see EXAMPLE below.
  378.  * 
  379.  *    TextAttr = a pointer to a TextAttr structure specifying the font
  380.  *       to be used for this XText font imagery.  If the TextAttr
  381.  *       argument is equal to NULL, the system's 80-column "topaz.font"
  382.  *       will be used.
  383.  * 
  384.  *    MaxTextWidth = Maximum number of characters per line.  This should 
  385.  *       be an even number, and if odd will be rounded up to the 
  386.  *       next even number.
  387.  * 
  388.  *    InitialFlags = Flags that will be preset in your XTextSupport's
  389.  *       Flags variable before anything is done with the structure.  
  390.  *       See the file xtext.h for the definitions of the XTextSupport 
  391.  *       structure's Flags.
  392.  * 
  393.  * 
  394.  * RESULT
  395.  *    Returns the address of the XTextSupport structure, or NULL
  396.  *    if there were any problems (usually out of memory).
  397.  * 
  398.  * 
  399.  * EXAMPLE
  400.  *    window = OpenWindow( ... );
  401.  *    xtext = MakeXTextSupport(window->RPort, &DiskFontTextAttr, 80, NULL);
  402.  *    - or, as another example, open a 320 screen and ... -
  403.  *    screen = OpenScreen( ... );
  404.  *    xtext = MakeXTextSupport(&screen->RastPort, NULL, 40, SLIM_XTEXT);
  405.  * 
  406.  * 
  407.  * SEE ALSO
  408.  *    MakeXTextFont(), XText(), UnmakeXTextSupport()
  409.  */
  410. struct XTextSupport *MakeXTextSupport(rport, textattr, maxwidth, flags)
  411. struct RastPort *rport;
  412. struct TextAttr *textattr;
  413. SHORT maxwidth;
  414. SHORT flags;
  415. {
  416.     struct XTextSupport *xtext;
  417.     SHORT i;
  418.  
  419.     maxwidth = (maxwidth + 1) & -2;
  420.  
  421.     if ((xtext = (struct XTextSupport *)AllocMem(sizeof(struct XTextSupport),
  422.             MEMF_CLEAR)) == NULL)
  423.         return (NULL);
  424.  
  425.     xtext->FrontPen = 1;
  426.     xtext->DrawMode = JAM2;
  427.     xtext->MaxTextWidth = maxwidth;
  428.     xtext->Flags = flags;
  429.  
  430.     /* If the user has specified no font, use 80-column "topaz.font" */
  431.     if (textattr == NULL) textattr = &DefaultXTextFont;
  432.  
  433.     xtext->CharHeight = textattr->ta_YSize;
  434.  
  435.     xtext->NormalTextPlane = AllocXTextPlane(xtext);
  436.     xtext->InverseTextPlane = AllocXTextPlane(xtext);
  437.     xtext->AllClearPlane = AllocXTextPlane(xtext);
  438.     xtext->AllSetPlane = AllocXTextPlane(xtext);
  439.  
  440.     if ((xtext->NormalTextPlane == NULL)
  441.             || (xtext->InverseTextPlane == NULL)
  442.             || (xtext->AllClearPlane == NULL)
  443.             || (xtext->AllSetPlane == NULL))
  444.         {
  445.         UnmakeXTextSupport(xtext);
  446.         return (NULL);
  447.         }
  448.  
  449.     for (i = 0; i < (xtext->CharHeight * maxwidth); i++)
  450.         xtext->AllSetPlane[i] = -1;
  451.  
  452.     xtext->OutputRPort = rport;
  453.  
  454.     InitBitMap(&xtext->TextBitMap, rport->BitMap->Depth, 
  455.             maxwidth * XTEXT_CHARWIDTH, xtext->CharHeight);
  456.  
  457.     if (MakeXTextFont(textattr, xtext, NORMAL_FONT) == NULL)
  458.         {
  459.         UnmakeXTextSupport(xtext);
  460.         return (NULL);
  461.         }
  462.  
  463.     for (i = 1; i < 8; i++)
  464.         xtext->FontData[i] = xtext->FontData[0];
  465.  
  466.     return(xtext);
  467. }
  468.  
  469.  
  470.  
  471. /* *** UnmakeXTextSupport() *************************************************
  472.  * 
  473.  * NAME
  474.  *    UnmakeXTextSupport  --  Free the XTextSupport structure and buffers
  475.  * 
  476.  * 
  477.  * SYNOPSIS
  478.  *    UnmakeXTextSupport(XTextSupport)
  479.  * 
  480.  * 
  481.  * FUNCTION
  482.  *    Frees the XTextSupport structure and buffers.
  483.  *
  484.  *
  485.  * INPUTS
  486.  *    XTextSupport = pointer to an XTextSupport structure (typically
  487.  *               created by a call to MakeXTextSupport() )
  488.  *
  489.  *
  490.  * RESULT
  491.  *    None
  492.  *
  493.  *
  494.  * SEE ALSO
  495.  *    MakeXTextSupport()
  496.  */
  497. VOID UnmakeXTextSupport(xtext)
  498. struct XTextSupport *xtext;
  499. {
  500.     if (xtext)
  501.         {
  502.         FreeRemember(&xtext->XTextKey, TRUE);
  503.         FreeMem(xtext, sizeof(struct XTextSupport));
  504.         }
  505. }
  506.  
  507.  
  508.